package cn.lili.modules.promotion.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.cglib.CglibUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.goods.client.GoodsClient;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.promotion.entity.dos.BoxLotteryTicket;
import cn.lili.modules.promotion.entity.dos.BoxMhgoods;
import cn.lili.modules.promotion.entity.dto.search.BoxSearchParams;
import cn.lili.modules.promotion.entity.vos.BoxWinningRecordVO;
import cn.lili.modules.promotion.service.BoxLotteryTicketService;
import cn.lili.modules.promotion.service.BoxMhgoodsService;
import cn.lili.modules.system.client.DictionaryClient;
import cn.lili.modules.system.constants.DictConstant;
import cn.lili.modules.system.entity.dos.Dictionary;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.lili.modules.promotion.entity.dos.BoxWinningRecord;
import cn.lili.modules.promotion.service.BoxWinningRecordService;
import cn.lili.modules.promotion.mapper.BoxWinningRecordMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.SecureRandom;
import java.util.Date;
import java.util.List;

/**
* @author asus
* @description 针对表【li_box_winning_record(中奖记录表)】的数据库操作Service实现
* @createDate 2023-11-22 17:32:13
*/
@Service
@Slf4j
public class BoxWinningRecordServiceImpl extends ServiceImpl<BoxWinningRecordMapper, BoxWinningRecord>
    implements BoxWinningRecordService{
    @Resource
    private BoxLotteryTicketService boxLotteryTicketService;
    @Resource
    private DictionaryClient dictionaryClient;
    @Resource
    private UserClient userClient;
    @Lazy
    @Resource
    private BoxMhgoodsService boxMhgoodsService;
    @Resource
    private GoodsClient goodsClient;

    @Override
    public ResultMessage<Object> pageBox(BoxSearchParams params) {
        log.info("boxWinningRecord page === {}", JSONObject.toJSONString(params));
        Page<BoxWinningRecord> mhgoodsPage = super.page(new Page<>(params.getPageNumber(), params.getPageSize()), this.createLambdaQueryWrapper(params));
        return ResultUtil.data(this.conversion(mhgoodsPage));
    }

    private Page<BoxWinningRecordVO> conversion(Page<BoxWinningRecord> paramsPage) {
        //复制page对象
        if (CollectionUtil.isEmpty(paramsPage.getRecords())) {
            return new Page<BoxWinningRecordVO>();
        }
        Page<BoxWinningRecordVO> resultPage = new Page<>();
        BeanUtils.copyProperties(paramsPage, resultPage);
        List<BoxWinningRecordVO> voList = CglibUtil.copyList(paramsPage.getRecords(), BoxWinningRecordVO::new);
        resultPage.setRecords(voList);

        //字典转换
        List<Dictionary> recordStatusList = dictionaryClient.getListByCode(DictConstant.WINNING_RECORD_STATUS_NAME);
        List<Dictionary> lotteryMethodList = dictionaryClient.getListByCode(DictConstant.LOTTERY_METHOD_NO);
        List<Dictionary> yesNoList = dictionaryClient.getListByCode(DictConstant.YES_NO);
        for (BoxWinningRecordVO boxWinningRecordVO : resultPage.getRecords()) {
            if (CollectionUtil.isNotEmpty(recordStatusList)) {
                for (Dictionary dictionary : recordStatusList) {
                    if (dictionary.getValue().equals(String.valueOf(boxWinningRecordVO.getWinningRecordStatus()))) {
                        boxWinningRecordVO.setWinningRecordStatusName(dictionary.getValueName());
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(lotteryMethodList)) {
                for (Dictionary dictionary : lotteryMethodList) {
                    if (dictionary.getValue().equals(String.valueOf(boxWinningRecordVO.getLotteryMethod()))) {
                        boxWinningRecordVO.setLotteryMethodName(dictionary.getValueName());
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(yesNoList)) {
                for (Dictionary dictionary : yesNoList) {
                    if (dictionary.getValue().equals(String.valueOf(boxWinningRecordVO.getShareOrNot()))) {
                        boxWinningRecordVO.setShareOrNotName(dictionary.getValueName());
                    }
                }
            }
        }
        return resultPage;
    }


    @Override
    public ResultMessage<Object> addBoxGoods(BoxWinningRecordVO boxOptionVO) {
        log.info("BoxWinningRecordVO addBoxGoods == {}", JSONObject.toJSONString(boxOptionVO));
        boxOptionVO.setId(null);
        return ResultUtil.data(super.save(boxOptionVO));
    }

    @Override
    public ResultMessage<Object> updateBoxGoods(BoxWinningRecordVO boxOptionVO) {
        log.info("BoxWinningRecordVO updateBoxGoods == {}", JSONObject.toJSONString(boxOptionVO));
        if (StringUtils.isEmpty(boxOptionVO.getId())) {
            throw new ServiceException("id为空");
        }
        return ResultUtil.data(super.updateById(boxOptionVO));
    }

    /**
     * 使用场景：用户强制退款
     */
    @Override
    public ResultMessage<Object> recycle(String id, String recycleRemark) {
        BoxWinningRecord boxWinningRecord = super.getById(id);
        if (boxWinningRecord == null) {
            log.error("未获取到，中奖记录 === {}",  id);
            return ResultUtil.error();
        }
        boxWinningRecord.setWinningRecordStatus(DictConstant.WINNING_RECORD_STATUS_02);
        boxWinningRecord.setRecycleRemark(recycleRemark);
        boxWinningRecord.setRecycleTime(new Date());
        super.updateById(boxWinningRecord);
        //如果有奖券就，作废
        if (StringUtils.isNotEmpty(boxWinningRecord.getLotteryTicketId())) {
            boxLotteryTicketService.cancellation(boxWinningRecord.getLotteryTicketId(), recycleRemark);
        }
        return ResultUtil.success();
    }


    /**
     * 中奖信息录入
     * @return 中奖记录信息
     */
    @Override
    public ResultMessage<Object> informationEntry(BoxWinningRecordVO boxWinningRecordVO) {
        log.info("informationEntry , boxWinningRecordVO == {}", JSONObject.toJSONString(boxWinningRecordVO));
        if (StringUtils.isEmpty(boxWinningRecordVO.getUsername())) {
            throw new ServiceException("用户名为空: username");
        }
        if (StringUtils.isEmpty(boxWinningRecordVO.getLotteryTicketNo())) {
            throw new ServiceException("奖券号码为空: lotteryTicketNo");
        }
        if (StringUtils.isEmpty(boxWinningRecordVO.getMhGoodsId())) {
            throw new ServiceException("盲盒ID为空: mhGoodsId");
        }
        String username = boxWinningRecordVO.getUsername();
        String lotteryTicketNo = boxWinningRecordVO.getLotteryTicketNo();
        String mhGoodsId = boxWinningRecordVO.getMhGoodsId();
        User user = userClient.getByUserName(username, SceneEnums.MEMBER.name());
        if (user == null || StringUtils.isEmpty(user.getId())) {
            throw new ServiceException("根据用户名未获取到用户信息："+ username);
        }
        BoxLotteryTicket boxLotteryTicket = boxLotteryTicketService.getOne(new LambdaUpdateWrapper<BoxLotteryTicket>().eq(BoxLotteryTicket::getDeleteFlag, Boolean.FALSE).eq(BoxLotteryTicket::getLotteryTicketNo, lotteryTicketNo).last("limit 1"));
        if (boxLotteryTicket == null || StringUtils.isEmpty(boxLotteryTicket.getId())) {
            throw new ServiceException("根据奖券号码未获取到奖券信息："+ lotteryTicketNo);
        }
        BoxMhgoods boxMhgoods = boxMhgoodsService.getById(mhGoodsId);
        if (boxMhgoods == null || StringUtils.isEmpty(boxMhgoods.getId())) {
            throw new ServiceException("根据盲盒编号未获取到盲盒信息："+ mhGoodsId);
        }
        if (StringUtils.isEmpty(boxMhgoods.getBigGoodsId())) {
            throw new ServiceException("盲盒大奖为空，请完善大奖奖品后重试");
        }
        Goods goods = goodsClient.getById(boxMhgoods.getBigGoodsId());
        if (goods == null || StringUtils.isEmpty(goods.getId())) {
            throw new ServiceException("请检查大奖商品，是否被删除：" + boxMhgoods.getBigGoodsId());
        }
        if (DictConstant.MH_STATUS_04.equals(boxMhgoods.getMhStatus())) {
            throw new ServiceException("盲盒已开奖，不能重复开奖");
        }
        //更新奖券状态
        LambdaUpdateWrapper<BoxLotteryTicket> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(BoxLotteryTicket::getMhId, boxMhgoods.getId());
        updateWrapper.set(BoxLotteryTicket::getActiveState, DictConstant.ACTIVE_STATE_02);
        boxLotteryTicketService.update(updateWrapper);

        updateWrapper.clear();
        updateWrapper.eq(BoxLotteryTicket::getLotteryTicketNo, lotteryTicketNo);
        updateWrapper.set(BoxLotteryTicket::getLotteryTicketStatus, DictConstant.LOTTERY_TICKET_STATUS_02);
        boxLotteryTicketService.update(updateWrapper);

        //更新盲盒状态
        boxMhgoods.setMhStatus(DictConstant.MH_STATUS_04);
        boxMhgoodsService.updateById(boxMhgoods);

        BoxWinningRecord boxWinningRecord = BeanUtil.toBean(boxWinningRecordVO, BoxWinningRecord.class);
        boxWinningRecord.setUsername(user.getUsername());
        boxWinningRecord.setUserId(user.getId());
        boxWinningRecord.setMhId(boxMhgoods.getId());
        boxWinningRecord.setMhName(boxMhgoods.getMhGoodsName());
        boxWinningRecord.setLotteryMethod(boxMhgoods.getLotteryMethod());
        boxWinningRecord.setLotteryTicketNo(boxLotteryTicket.getLotteryTicketNo());
        boxWinningRecord.setLotteryTicketId(boxLotteryTicket.getId());
        boxWinningRecord.setWinningRecordStatus(DictConstant.WINNING_RECORD_STATUS_01);
        boxWinningRecord.setGoodsId(goods.getId());
        boxWinningRecord.setGoodsName(goods.getGoodsName());
        boxWinningRecord.setOrderTime(boxLotteryTicket.getCreateTime());
        boxWinningRecord.setDrawingTime(new Date());
        boxWinningRecord.setShareOrNot(DictConstant.YES_NO_00);
        return ResultUtil.data(super.save(boxWinningRecord));
    }

    private LambdaQueryWrapper<BoxWinningRecord> createLambdaQueryWrapper(BoxSearchParams params) {
        LambdaQueryWrapper<BoxWinningRecord> winningRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();

        if (StringUtils.isNotEmpty(params.getGoodsName())) {
            winningRecordLambdaQueryWrapper.like(BoxWinningRecord::getGoodsName, params.getGoodsName());
        }
        if (StringUtils.isNotEmpty(params.getUsername())) {
            winningRecordLambdaQueryWrapper.like(BoxWinningRecord::getUsername, params.getUsername());
        }
        if (StringUtils.isNotEmpty(params.getUserId())) {
            winningRecordLambdaQueryWrapper.eq(BoxWinningRecord::getUserId, params.getUserId());
        }
        if (StringUtils.isNotEmpty(params.getMhName())) {
            winningRecordLambdaQueryWrapper.like(BoxWinningRecord::getMhName, params.getMhName());
        }
        if (StringUtils.isNotEmpty(params.getGoodsId())) {
            winningRecordLambdaQueryWrapper.like(BoxWinningRecord::getGoodsId, params.getGoodsId());
        }
        if (params.getWinningRecordStatus() != null) {
            winningRecordLambdaQueryWrapper.eq(BoxWinningRecord::getWinningRecordStatus, params.getWinningRecordStatus());
        }
        if (params.getStartDrawingTime() != null) {
            winningRecordLambdaQueryWrapper.ge(BoxWinningRecord::getDrawingTime, params.getStartDrawingTime());
        }
        if (params.getEndDrawingTime() != null) {
            winningRecordLambdaQueryWrapper.le(BoxWinningRecord::getDrawingTime, params.getEndDrawingTime());
        }
        if (params.getStartOrderTime() != null) {
            winningRecordLambdaQueryWrapper.ge(BoxWinningRecord::getOrderTime, params.getStartOrderTime());
        }
        if (params.getEndOrderTime() != null) {
            winningRecordLambdaQueryWrapper.le(BoxWinningRecord::getOrderTime, params.getEndOrderTime());
        }

        if (StringUtils.isNotEmpty(params.getLotteryTicketNo())) {
            winningRecordLambdaQueryWrapper.like(BoxWinningRecord::getLotteryTicketNo, params.getLotteryTicketNo());
        }
        if (StringUtils.isNotEmpty(params.getLogisticsTrackingNumber())) {
            winningRecordLambdaQueryWrapper.like(BoxWinningRecord::getLogisticsTrackingNumber, params.getLogisticsTrackingNumber());
        }
        winningRecordLambdaQueryWrapper.eq(BoxWinningRecord::getDeleteFlag, Boolean.FALSE);
        winningRecordLambdaQueryWrapper.orderByDesc(BoxWinningRecord::getCreateTime);
        return winningRecordLambdaQueryWrapper;
    }


    /**
     * 中奖记录
     * @return 中奖记录
     */
    @Override
    public ResultMessage<Object> winning() {
        String currentId = UserContext.getCurrentId();
        if (StringUtils.isEmpty(currentId)) {
            throw new ServiceException("登陆已过期，请重新登陆");
        }
        LambdaQueryWrapper<BoxWinningRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BoxWinningRecord::getUserId, UserContext.getCurrentId());
        return ResultUtil.data(super.list(queryWrapper));
    }
}




